/*
 * Copyright 2021 Roberto Leinardi.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.leinardi.ohos.speeddial;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;

public class UiUtils {

    private UiUtils() {
    }

    /**
     * 设置状态栏颜色
     *
     * @param color 状态栏颜色
     */
    public static void setStatusBarColor(int color) {
        WindowManager.getInstance().getTopWindow().get().setStatusBarColor(color);
    }

    public static int getColor(Context context, int colorRes) {
        int color = 0;
        try {
            color = context.getResourceManager().getElement(colorRes).getColor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return color;
    }

    public static float getDimensionValue(Context context, int dimenRes) {
        float value = 0;
        try {
            value = context.getResourceManager().getElement(dimenRes).getFloat();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;
    }

    public static int getPrimaryColor(Context context) {
        int color = 0;
        try {
            color = context.getResourceManager().getElement(ResourceTable.Color_inbox_primary).getColor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return color;
    }

    public static int getOnSecondaryColor(Context context) {
        int color = 0;
        try {
            color = context.getResourceManager().getElement(ResourceTable.Color_material_white_1000).getColor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return color;
    }

    public static int getAccentColor(Context context) {
        int color = 0;
        try {
            color = context.getResourceManager().getElement(ResourceTable.Color_colorAccent).getColor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return color;
    }

    public static int dpToPx(Context context, float dp) {
        return AttrHelper.vp2px(dp, context);
    }

    /**
     * Fade out animation.
     *
     * @param view view to animate.
     */
    public static void fadeOutAnim(final Component view) {
        view.setAlpha(1F);
        view.setVisibility(Component.VISIBLE);
        fadeAnim(view, false);
    }

    /**
     * Fade in animation.
     *
     * @param view view to animate.
     */
    public static void fadeInAnim(final Component view) {
        view.setAlpha(0);
        view.setVisibility(Component.VISIBLE);
        fadeAnim(view, true);
    }

    private static void fadeAnim(final Component view, boolean isFadeIn) {
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setDuration(isFadeIn?
                getConfigDuration(view.getContext(), ResourceTable.Integer_sd_open_animation_duration):
                getConfigDuration(view.getContext(), ResourceTable.Integer_sd_close_animation_duration));
        animatorValue.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        animatorValue.setValueUpdateListener((animatorValue1, v) -> view.setAlpha(isFadeIn ? v : (1 - v)));
        animatorValue.setStateChangedListener(new AnimStateChangedListener(){
            @Override
            public void onEnd(Animator animator) {
                if(!isFadeIn) {
                    view.setVisibility(Component.HIDE);
                }
            }
        });
        animatorValue.start();
    }

    /**
     * SpeedDial opening animation.
     *
     * @param view        view that starts that animation.
     * @param startOffset a delay in time to start the animation
     */
    public static void enlargeAnim(Component view, long startOffset) {
        view.setVisibility(Component.VISIBLE);

        AnimatorProperty property = new AnimatorProperty();
        property.setDuration(getConfigDuration(view.getContext(), ResourceTable.Integer_sd_open_animation_duration));
        property.setTarget(view);
        property.setDelay(startOffset);
        property.scaleXFrom(0.5f).scaleX(1f);
        property.scaleYFrom(0.5f).scaleY(1f);
        property.alphaFrom(0f).alpha(1f);
        property.moveFromY(getDimensionValue(view.getContext(), ResourceTable.Float_fab_margin_top_and_bottom)).moveToY(0f);
        property.start();
    }

    /**
     * SpeedDial closing animation.
     *
     * @param view        view that starts that animation.
     * @param startOffset a delay in time to start the animation
     */
    public static void shrinkAnim(final Component view, long startOffset) {
        view.setVisibility(Component.VISIBLE);

        AnimatorProperty property = new AnimatorProperty();
        property.setDuration(getConfigDuration(view.getContext(), ResourceTable.Integer_sd_open_animation_duration));
        property.setTarget(view);
        property.setDelay(startOffset);
        property.scaleXFrom(1f).scaleX(0.5f);
        property.scaleYFrom(1f).scaleY(0.5f);
        property.alphaFrom(1f).alpha(0f);
        property.moveFromY(0f).moveToY(getDimensionValue(view.getContext(), ResourceTable.Float_fab_margin_top_and_bottom));
        property.setStateChangedListener(new AnimStateChangedListener(){
            @Override
            public void onEnd(Animator animator) {
                view.setVisibility(Component.HIDE);
            }
        });
        property.start();
    }

    /**
     * Closing animation.
     *
     * @param view       view that starts that animation.
     * @param removeView true to remove the view when the animation is over, false otherwise.
     */
    public static void shrinkAnim(final Component view, final boolean removeView) {
        try{
            AnimatorProperty property = new AnimatorProperty();
            property.setDuration(getConfigDuration(view.getContext(), ResourceTable.Integer_sd_close_animation_duration));
            property.setTarget(view);
            property.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
            property.alphaFrom(1.0f).alpha(0f);
            property.setStateChangedListener(new AnimStateChangedListener() {
                @Override
                public void onEnd(Animator animator) {
                    if (removeView) {
                        ComponentContainer parent = (ComponentContainer) view.getComponentParent();
                        if (parent != null) {
                            parent.removeComponent(view);
                        }
                    } else {
                        view.setVisibility(Component.HIDE);
                    }
                }
            });
            property.start();
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * Rotate a view of the specified degrees.
     *
     * @param floatingActionButton    The FloatingActionButton to rotate.
     * @param animate true to animate the rotation, false to be instant.
     * @see #rotateBackward(FloatingActionButton, float, boolean)
     */
    public static void rotateForward(FloatingActionButton floatingActionButton, float angle, boolean animate) {
        Image iconImage = floatingActionButton.getIconImage();
        iconImage.setRotation(-angle);

        AnimatorProperty property = new AnimatorProperty();
        property.setDuration(animate ? getConfigDuration(floatingActionButton.getContext(), ResourceTable.Integer_sd_rotate_animation_duration) : 0);
        property.setTarget(iconImage);
        property.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        property.rotate(0);
        property.start();
    }

    /**
     * Rotate a view back to its default angle (0°).
     *
     * @param floatingActionButton    The FloatingActionButton to rotate.
     * @param animate true to animate the rotation, false to be instant.
     */
    public static void rotateBackward(FloatingActionButton floatingActionButton, float angle, boolean animate) {
        Image iconImage = floatingActionButton.getIconImage();
        iconImage.setRotation(angle);

        AnimatorProperty property = new AnimatorProperty();
        property.setDuration(animate ? getConfigDuration(floatingActionButton.getContext(), ResourceTable.Integer_sd_rotate_animation_duration) : 0);
        property.setTarget(iconImage);
        property.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        property.rotate(0);
        property.start();
    }

    private static int getConfigDuration(Context context, int resId) {
        int duration = 0;
        try {
            duration = context.getResourceManager().getElement(resId).getInteger();
        }catch (Exception e){
            e.printStackTrace();
        }
        return duration;
    }

}
